package com.leon.socket;

import com.leon.NetworkServer;

import java.io.Closeable;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import static com.leon.constant.ServerState.*;

/**
 * 原生Socket网络服务器
 * Copyright (c) 2021 Choice, Inc.
 * All Rights Reserved.
 * Choice Proprietary and Confidential.
 *
 * @author longmu
 * @since 2021/9/10
 */
public class SocketServer implements NetworkServer {

    private static ServerSocket serverSocket;


    private volatile int state;

    @Override
    public void init(int port) {
        if (state != INITED) {
            throw new RuntimeException("this server is already inited!");
        }
        try {
            serverSocket = new ServerSocket(port);
            state = INITED;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void start() {

        try {
            while (this.state != CLOSED) {
                Socket socket = serverSocket.accept();
                if (null != socket) {
                    new Thread(new Handler(socket, 1024)).start();
                } else {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        close();
                    }
                }
            }
            state = STARTED;
        } catch (IOException e) {
            System.out.println("serverSocket start error, msg: " + e.getMessage());
            close();
        }
    }

    @Override
    public void close() {

        try {
            if (!serverSocket.isClosed()) {
                serverSocket.close();
            }
            state = CLOSED;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    static class Handler implements Closeable, Runnable {

        final Socket socket;
        int bufferSize;

        Handler(Socket socket, int bufferSize) {
            this.socket = socket;
            this.bufferSize = bufferSize;
        }

        @Override
        public void run() {
            try {
                byte[] buffer = new byte[this.bufferSize];
                this.socket.getInputStream().read(buffer);
                byte[] output = process(buffer);
                this.socket.getOutputStream().write(output);
            } catch (Exception e) {
                try {
                    close();
                } catch (IOException ex) {
                    System.out.println("socket close error");
                }
            }
        }

        private byte[] process(byte[] intput) {
            System.out.println("start process input...");
            byte[] output = null;
            System.out.println(new String(intput));
            //todo 逻辑处理
            return output;
        }

        @Override
        public void close() throws IOException {
            if (null != this.socket && null != this.socket.getInputStream()) {
                this.socket.getInputStream().close();
                this.socket.close();
            }
            if (null != this.socket) {
                this.socket.close();
            }
        }
    }
}